<template>
  <div class="comparioson-container shadow-lg border border-slate-200 border-solid">
      <toolbar
        :config.sync="config"
        :disabled="loading"
        :themes="Object.keys(themes)"
        :languages="Object.keys(languages)"
        @editable="(edit)=>config.disabled = !edit"
        @focus="(autofocus) => config.autofocus = autofocus"
        @theme="theme => config.theme = theme"
        @clear="clear"
        @copy="handleCopyBtnClick"
        @language="ensureLanguageCode"
        @save="save"
      />
      <editor
        v-if="currentLangCode"
        :config="config"
        :theme="currentTheme"
        :language="currentLangCode.language"
        :code="currentLangCode.code"
      />
  </div>
</template>
<script lang="ts">
import { defineComponent, reactive, computed, shallowRef, onBeforeMount } from "vue";
import { usePageContext } from 'vike-vue/usePageContext'
import languages from "./languages";
import * as themes from "./themes";
import Toolbar from "./components/toolbar.vue";
import Editor from "./editor.vue";
import {saveTxt} from '@/utils/tool'
import { useClipboard } from '@vueuse/core'
import {
  message,
} from "ant-design-vue";
import { cloneDeep } from "lodash";

export default defineComponent({
  name: "vue-codemirror-example",
  title: "Example Source Code",
  url: import.meta.url,
  components: {
    Toolbar,
    Editor,
  },
  setup() {
    const ctx = usePageContext()
    const config = reactive({
      disabled: false,
      indentWithTab: true,
      tabSize: 2,
      autofocus: true,
      height: "auto",
      placeholder: "Write your code here...",
      language: "javascript",
      autoDestroy: true,
      theme: "oneDark",
    });

    const loading = shallowRef(false);
    const langCodeMap = reactive(
      new Map<string, { code: string; language: () => any }>()
    );
    const currentLangCode = computed(() => langCodeMap.get(config.language)!);
    const currentTheme = computed(() => {
      return config.theme !== "default" ? (themes as any)[config.theme] : void 0;
    });

    /* 清空 */
    const clear = () => {
      currentLangCode.value.code = "";
    };

    const save = () => {
      const content = cloneDeep(currentLangCode.value.code)
      if (!content) {
        return message.error('请确认保存文件内容！')
      }
      const contentType = currentLangCode.value.language?.name || config.language
      const ext= currentLangCode.value?.suffix
      message.success('正在保存文件到临时下载目录...')
      saveTxt(content,contentType+ext ,'application/octet-stream')
    }

    const { copy } = useClipboard({ legacy: true })
    function handleCopyBtnClick(text: string) {
      if (!currentLangCode.value.code) {
        return message.error('请确认复制内容！')
      }
      try {
        copy(currentLangCode.value.code)
        message.success('复制成功')
      }
      catch (e) {
        console.log(e)
        message.error('复制失败')
      }
    }

    const ensureLanguageCode = async (targetLanguage: string) => {
      config.language = targetLanguage;
      loading.value = true;
      const delayPromise = () =>
        new Promise((resolve) => window.setTimeout(resolve, 260));
      if (langCodeMap.has(targetLanguage)) {
        await delayPromise();
      } else {
        const [result] = await Promise.all([languages[targetLanguage](), delayPromise()]);
        langCodeMap.set(targetLanguage, result.default);
      }
      loading.value = false;
    };

    // HACK: Make sure the first screen the user sees is the loading placeholder
    loading.value = true;
    onBeforeMount(() => {
      // init default language & code
      ensureLanguageCode(config.language);
    });

    return {
      loading,
      config,
      themes,
      clear,
      handleCopyBtnClick,
      languages,
      currentTheme,
      currentLangCode,
      ensureLanguageCode,
      save
    };
  },
});
</script>

<style lang="scss" scoped>
@import "./style.scss";
</style>
